﻿import { DataCenterS, ModuleC, ModuleManager, ModuleS, SoundManager } from "odin";
import { Consts } from "../../Consts";
import { MonsterModuleS } from "../monster/MonsterModule";

/**
 * @Author: zhaolei
 * @Date: 2022-08-01 10:35:52
 * @LastEditors: zhaolei
 * @Description: 武器管理模块
 * 服务端-负责命中逻辑，玩家的伤害判断
 * 客户端-负责武器的拾取，开火，武器命中的检测
 */
export class WeaponModuleS extends ModuleS<WeaponModuleC, null> {

	/**
	 * 命中目标，由客户端调用
	 * @param guid 命中的目标
	 */
	public net_hit(guid: string) {
		//判断命中的是否是玩家（未实现）
		if (guid === Consts.MONSTER) {
			// 怪物
			this.hitMonster();
		} else {
			// 命中地图障碍物
			const obj = MWCore.GameObject.find(guid);
			if (obj) {
				const location = obj.location;
				location.z -= 10;
				obj.location = location;
			}
			//判断是否为npc，如果是发送NPCdie的方法（未实现）
		}
	}

	public override onAwake(): void {
		DataCenterS.instance.onPlayerJoined.add(player => {
			player.character.isCollisionWithOtherCharacter = false;
		});
	}
	/**
	 * 命中怪物，让怪物模块处理伤害逻辑
	 */
	private hitMonster() {
		const monsterModule = ModuleManager.instance.getModule(MonsterModuleS);
		monsterModule.onMonsterHit();
	}
}
export class WeaponModuleC extends ModuleC<WeaponModuleS, null> {
	/**
	 * 当前的武器ID
	 */
	private _weaponId: number = 0;
	/**
	 * 是否射击中
	 */
	private _isShoot: boolean;
	/**
	 * 射击倒计时
	 */
	private _shootTime: number = 0;
	/**
	 * 枪口火焰特效
	 */
	private _fire: GamePlay.EffectSystem;
	/**
	 * 武器对象
	 */
	private _weaponObject: MWCore.GameObject;
	/**
	 * 开火音效对象ID
	 */
	private _fireSound: string;

	/**
	 * 玩家拿起武器，所有玩家拿起武器时都会调用该方法
	 * @param weaponId 
	 */
	public pickWeapon(player: GamePlay.Player, weaponId: number) {

		// 生成投掷对象
		let project = MWCore.GameObject.spawnGameObject("14090", true) as GamePlay.ProjectileObj;

		//创建子弹模型
		let bulletMesh = MWCore.GameObject.spawnGameObject("60842", true) as MWCore.GameObject;
		bulletMesh.scale = Type.Vector.one;
		bulletMesh.setCollision(Type.PropertyStatus.Off);

		const weaponObject = MWCore.GameObject.spawnGameObject(Consts.WEAPON_GUID);
		// 把武器挂载到玩家右手
		player.character.attachGameObjectToCharacter(weaponObject, GamePlay.CharacterSocketType.Right_Hand);
		// 微调武器的位置和朝向来贴合右手
		weaponObject.setRelativeLocation(new Type.Vector(26, 0, -10));
		weaponObject.setRelativeRotation(Type.Rotation.zero);

		//将子弹模型绑定到投掷物上
		bulletMesh.attachToGameObject(project);

		// 玩家变成持枪姿态
		player.character.animationStance = GamePlay.AnimationStanceType.RifleStand;
		// 玩家朝向模式改为控制器方向
		player.character.moveFacingDirection = GamePlay.MoveFacingDirection.ControllerDirection;

		// 保存自己的武器数据
		if (player.getPlayerID() == this.currentPlayerId) {
			this._weaponId = weaponId;
			this._weaponObject = weaponObject;
		}
	}

	/**
	 * 开始射击
	 */
	public startShoot() {
		// 有武器才能射击
		this._isShoot = this._weaponId > 0;
		this._shootTime = 0;
		if (this._isShoot) {
			this._fireSound = SoundManager.instance.playSound(Consts.SHOOT_SOUND, 0);
			this.currentPlayer.character.animationStance = GamePlay.AnimationStanceType.RifleAimStand;
			if (!this._fire) {
				this._fire = MWCore.GameObject.spawnGameObject(Consts.SHOOT_EFFECT) as GamePlay.EffectSystem;
				this._fire.setLoop(true);

				this._fire.attachToGameObject(this._weaponObject);
				this._fire.setRelativeLocation(new Type.Vector(100, 0, 0));
				this._fire.setRelativeRotation(new Type.Rotation(-90, 0, 180));
			}
			this._fire.play();
		}

	}

	/**
	 * 停止射击
	 */
	public stopShoot() {
		if (this._isShoot) {
			SoundManager.instance.stopSound(this._fireSound);
			this._isShoot = false;
			this.currentPlayer.character.animationStance = GamePlay.AnimationStanceType.RifleStand;
			this._fire.stop();
		}
	}

	/**
	 * 武器碰撞检测
	 * @param dt 
	 */
	public onUpdate(dt: number): void {
		if (this._isShoot) {
			if (this._shootTime <= 0) {
				this._shootTime = 0.2;
				this.currentPlayer.character.playAnimationLocally(Consts.SHOOT_ANIMATION);
				//每隔0.2秒检查一次
				this.checkCollision();
			} else {
				this._shootTime -= dt;
			}
		}
	}

	/**
	 * 检测碰撞物体
	 */
	private checkCollision() {
		const charLoc = this.currentPlayer.character.location;//玩家位置
		const forward = this.currentPlayer.character.cameraSystem.cameraWorldTransform.getForwardVector();//玩家朝向

		// 武器为喷火器，通过矩形检测，检测火焰范围内的击中物体（改为激光，变为射线检测）
		//const objs = GamePlay.boxOverlapInLevel(charLoc.addition(forward.multiply(1)), charLoc.addition(forward.multiply(10000)), 100, 100, false);
		const objs = GamePlay.lineTrace(GamePlay.getCurrentPlayer().character,charLoc,charLoc.addition(forward.multiply(1000)),true,true);
		for (const obj of objs) {
			//if (!GamePlay.isCharacter(objs) {
				if (obj.tag === "block" || obj.guid === Consts.MONSTER) {
					// 命中的是玩家或者NPC（未实现）
					this.server.net_hit(obj.guid);
				}
			//}
		}
	}
}

